package com.zg.scf.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zg.common.core.dao.auth.AuthUserDao;
import com.zg.common.core.dao.scf.CompanyBusinessAlertDao;
import com.zg.common.core.dao.scf.ScfUserCompanyDao;
import com.zg.common.core.dao.scf.entity.CompanyBusinessAlert;
import com.zg.common.core.dao.scf.entity.ScfUserCompany;
import com.zg.common.core.exception.BusinessException;
import com.zg.scf.enm.AlertTypeEnum;
import com.zg.scf.domain.req.AlertIgnoreAddReq;
import com.zg.scf.domain.req.AlertPageReq;
import com.zg.scf.domain.req.AlertProcessAddReq;
import com.zg.scf.domain.req.AlertServiceDueEditReq;
import com.zg.scf.domain.vo.CompanyBusinessAlertVo;
import com.zg.scf.service.CompanyBusinessAlertService;
import com.zg.scf.util.DataScopeUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class CompanyBusinessAlertServiceImpl implements CompanyBusinessAlertService {

    private final CompanyBusinessAlertDao companyBusinessAlertDao;
    private final DataScopeUtil dataScopeUtil;
    private final ScfUserCompanyDao scfUserCompanyDao;
    private final AuthUserDao authUserDao;

    @Override
    public IPage<CompanyBusinessAlertVo> serviceDuePage(AlertPageReq req) {
        return page(AlertTypeEnum.SERVICE_DUE, req);
    }

    @Override
    public IPage<CompanyBusinessAlertVo> longTermInactivation(AlertPageReq req) {
        return page(AlertTypeEnum.LONG_TERM_INACTIVATION, req);
    }

    @Override
    public IPage<CompanyBusinessAlertVo> noBusinessPage(AlertPageReq req) {
        return page(AlertTypeEnum.NO_BUSINESS, req);
    }

    @Override
    public IPage<CompanyBusinessAlertVo> violationPage(AlertPageReq req) {
        return page(AlertTypeEnum.VIOLATION, req);
    }

    @Override
    public IPage<CompanyBusinessAlertVo> creditAmountErrorPage(AlertPageReq req) {
        return page(AlertTypeEnum.CREDIT_AMOUNT_ERROR, req);
    }

    @Override
    public IPage<CompanyBusinessAlertVo> financingAmountErrorPage(AlertPageReq req) {
        return page(AlertTypeEnum.FINANCING_AMOUNT_ERROR, req);
    }

    @Override
    public IPage<CompanyBusinessAlertVo> agreementErrorPage(AlertPageReq req) {
        return page(AlertTypeEnum.AGREEMENT_ERROR, req);
    }

    @Override
    public IPage<CompanyBusinessAlertVo> repaymentErrorPage(AlertPageReq req) {
        return page(AlertTypeEnum.REPAYMENT_ERROR, req);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void processAdd(AlertProcessAddReq req) {
        CompanyBusinessAlert companyBusinessAlert = companyBusinessAlertDao.getById(req.getId());
        if (companyBusinessAlert == null) {
            BusinessException.happen("请选择正确的预警数据");
        }
        if (companyBusinessAlert.getAlertProcessTime() != null) {
            BusinessException.happen("预警数据已被处理");
        }
        companyBusinessAlert.setAlertProcessTime(req.getAlertProcessTime());
        companyBusinessAlert.setAlertResult(req.getAlertResult());
        companyBusinessAlert.setAlertProcessNotes(req.getAlertProcessNotes());
        companyBusinessAlertDao.updateById(companyBusinessAlert);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void serviceDueEdit(AlertServiceDueEditReq req) {
        CompanyBusinessAlert companyBusinessAlert = companyBusinessAlertDao.getById(req.getId());
        if (companyBusinessAlert == null) {
            BusinessException.happen("请选择正确的预警数据");
        }
        companyBusinessAlert.setAlertProcessTime(DateUtil.date());
        companyBusinessAlert.setAlertResult("服务延期");
        companyBusinessAlert.setAlertProcessNotes("服务期限更新至" + DateUtil.formatDateTime(req.getServiceTerm()));
        companyBusinessAlertDao.updateById(companyBusinessAlert);

        // TODO 更新企业的服务期限
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void companyLogoutAdd(Long id) {
        CompanyBusinessAlert companyBusinessAlert = companyBusinessAlertDao.getById(id);
        if (companyBusinessAlert == null) {
            BusinessException.happen("请选择正确的预警数据");
        }
        companyBusinessAlert.setAlertProcessTime(DateUtil.date());
        companyBusinessAlert.setAlertResult("企业注销");
        companyBusinessAlert.setAlertProcessNotes("企业注销");
        companyBusinessAlertDao.updateById(companyBusinessAlert);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void ignoreAdd(AlertIgnoreAddReq req) {
        CompanyBusinessAlert companyBusinessAlert = companyBusinessAlertDao.getById(req.getId());
        if (companyBusinessAlert == null) {
            BusinessException.happen("请选择正确的预警数据");
        }
        companyBusinessAlert.setAlertProcessTime(DateUtil.date());
        companyBusinessAlert.setAlertResult("忽略");
        companyBusinessAlert.setAlertProcessNotes(req.getAlertProcessNotes());
        companyBusinessAlertDao.updateById(companyBusinessAlert);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void creditAmountEdit(Long id) {
        CompanyBusinessAlert companyBusinessAlert = companyBusinessAlertDao.getById(id);
        if (companyBusinessAlert == null) {
            BusinessException.happen("请选择正确的预警数据");
        }
        Long businessBankAmount = companyBusinessAlert.getBusinessBankAmount();
        // TODO 调整授信额度

        companyBusinessAlert.setAlertProcessTime(DateUtil.date());
        companyBusinessAlert.setAlertResult("调整授信额度");
        companyBusinessAlert.setAlertProcessNotes("授信额度调整至" + businessBankAmount);
        companyBusinessAlertDao.updateById(companyBusinessAlert);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void financingAmountEdit(Long id) {
        CompanyBusinessAlert companyBusinessAlert = companyBusinessAlertDao.getById(id);
        if (companyBusinessAlert == null) {
            BusinessException.happen("请选择正确的预警数据");
        }
        Long businessBankAmount = companyBusinessAlert.getBusinessBankAmount();
        // TODO 更新融资额度

        companyBusinessAlert.setAlertProcessTime(DateUtil.date());
        companyBusinessAlert.setAlertResult("更新融资额度");
        companyBusinessAlert.setAlertProcessNotes("融资额度更新至" + businessBankAmount);
        companyBusinessAlertDao.updateById(companyBusinessAlert);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void agreementAdd(Long id) {
        CompanyBusinessAlert companyBusinessAlert = companyBusinessAlertDao.getById(id);
        if (companyBusinessAlert == null) {
            BusinessException.happen("请选择正确的预警数据");
        }
        companyBusinessAlert.setAlertProcessTime(DateUtil.date());
        companyBusinessAlert.setAlertResult("签章");
        companyBusinessAlert.setAlertProcessNotes("已完成签署");
        companyBusinessAlertDao.updateById(companyBusinessAlert);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void repaymentEdit(Long id) {
        CompanyBusinessAlert companyBusinessAlert = companyBusinessAlertDao.getById(id);
        if (companyBusinessAlert == null) {
            BusinessException.happen("请选择正确的预警数据");
        }
        // TODO 回退还款状态

        companyBusinessAlert.setAlertProcessTime(DateUtil.date());
        companyBusinessAlert.setAlertResult("回退状态");
        companyBusinessAlert.setAlertProcessNotes("已退回状态");
        companyBusinessAlertDao.updateById(companyBusinessAlert);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void serviceDueAdd() {
        // TODO 查询所有融资企业和金融机构
        List companyList = null;
        List<CompanyBusinessAlert> alertList = new ArrayList<>();
        for (Object o : companyList) {
            Date expireDate = null;
            long betweenDay = DateUtil.betweenDay(DateUtil.date(), expireDate, false);
            if (betweenDay > -15 && betweenDay < 15) {
                CompanyBusinessAlert companyBusinessAlert = new CompanyBusinessAlert();
                Long companyId = null;
                String creditCode = null;
                String companyName = null;
                String companyType = null;
                companyBusinessAlert.setCompanyId(companyId);
                companyBusinessAlert.setCreditCode(creditCode);
                companyBusinessAlert.setCompanyName(companyName);
                companyBusinessAlert.setCompanyType(companyType);
                companyBusinessAlert.setAlertType(AlertTypeEnum.SERVICE_DUE.getCode());
                companyBusinessAlert.setAlertContent("服务即将到期");
                companyBusinessAlert.setAlertTriggerTime(DateUtil.date());
                companyBusinessAlert.setBusinessTime(expireDate);
                alertList.add(companyBusinessAlert);
                if (betweenDay < 0) {
                    companyBusinessAlert.setAlertContent("服务已到期");
                }
            }
        }

        addAlert(alertList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void longTermInactivationAdd() {
        // TODO 查询所有融资企业和金融机构
        List companyList = null;
        Map<Long, Object> companyMap = new HashMap<>();
        List<ScfUserCompany> scfUserCompanyList = scfUserCompanyDao.list(
                new LambdaQueryWrapper<ScfUserCompany>()
                        .in(ScfUserCompany::getCompanyId, companyMap.keySet())
        );
        if (scfUserCompanyList.isEmpty()) {
            return;
        }
        Map<Long, ScfUserCompany> scfUserOrgMap = scfUserCompanyList
                .stream().collect(Collectors.toMap(ScfUserCompany::getUserId, Function.identity()));


        List<CompanyBusinessAlert> alertList = new ArrayList<>();
        for (Object o : companyList) {
            Date expireDate = null;
            long betweenDay = DateUtil.betweenDay(DateUtil.date(), expireDate, false);
            if (betweenDay > -15 && betweenDay < 15) {
                CompanyBusinessAlert companyBusinessAlert = new CompanyBusinessAlert();
                Long companyId = null;
                String creditCode = null;
                String companyName = null;
                String companyType = null;
                companyBusinessAlert.setCompanyId(companyId);
                companyBusinessAlert.setCreditCode(creditCode);
                companyBusinessAlert.setCompanyName(companyName);
                companyBusinessAlert.setCompanyType(companyType);
                companyBusinessAlert.setAlertType(AlertTypeEnum.SERVICE_DUE.getCode());
                companyBusinessAlert.setAlertContent("服务即将到期");
                companyBusinessAlert.setAlertTriggerTime(DateUtil.date());
                companyBusinessAlert.setBusinessTime(expireDate);
                alertList.add(companyBusinessAlert);
                if (betweenDay < 0) {
                    companyBusinessAlert.setAlertContent("服务已到期");
                }
            }
        }

        addAlert(alertList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void noBusinessAdd() {

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void violationAdd() {

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void creditAmountErrorAdd() {

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void financingAmountErrorAdd() {

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void agreementErrorAdd() {

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void repaymentErrorAdd() {

    }

    private IPage<CompanyBusinessAlertVo> page(AlertTypeEnum alertTypeEnum, AlertPageReq req) {
        Long orgDataScope = dataScopeUtil.getOrgDataScope();
        IPage<CompanyBusinessAlert> page = companyBusinessAlertDao.page(
                new Page<>(req.getPage(), req.getPageSize()),
                new LambdaQueryWrapper<CompanyBusinessAlert>()
                        .eq(CompanyBusinessAlert::getAlertType, alertTypeEnum.getCode())
                        .eq(Objects.nonNull(orgDataScope), CompanyBusinessAlert::getCompanyId, orgDataScope)
                        .like(StrUtil.isNotBlank(req.getCompanyName()), CompanyBusinessAlert::getCompanyName,
                                "%" + req.getCompanyName() + "%")
                        .eq(StrUtil.isNotBlank(req.getCompanyType()), CompanyBusinessAlert::getCompanyType,
                                req.getCompanyType())
        );
        IPage<CompanyBusinessAlertVo> result = new Page<>();
        BeanUtil.copyProperties(page, result);
        result.setRecords(BeanUtil.copyToList(page.getRecords(), CompanyBusinessAlertVo.class));
        return result;
    }



    private void addAlert(List<CompanyBusinessAlert> alertList) {
        List<CompanyBusinessAlert> addList = new ArrayList<>();
        for (CompanyBusinessAlert companyBusinessAlert : alertList) {
            boolean exists = companyBusinessAlertDao.exists(
                    new LambdaQueryWrapper<CompanyBusinessAlert>()
                            .eq(CompanyBusinessAlert::getCompanyId, companyBusinessAlert.getCompanyId())
                            .eq(CompanyBusinessAlert::getCreditCode, companyBusinessAlert.getCreditCode())
                            .eq(CompanyBusinessAlert::getCompanyType, companyBusinessAlert.getCompanyType())
                            .eq(CompanyBusinessAlert::getAlertType, companyBusinessAlert.getAlertType())
                            .eq(CompanyBusinessAlert::getAlertContent, companyBusinessAlert.getAlertContent())
                            .eq(CompanyBusinessAlert::getBusinessTime, companyBusinessAlert.getBusinessTime())
            );
            if (!exists) {
                addList.add(companyBusinessAlert);
            }
        }
        if (!addList.isEmpty()) {
            companyBusinessAlertDao.saveBatch(addList);
        }
    }
}
